package cn.com.cpic.insurance.rulecheck.core.expression;

import cn.com.cpic.insurance.rulecheck.core.Context;

/**
 * 
 * 
 * @author 代波
 * @since 2011-8-14
 */
public class CompareExpression<V extends Comparable<V>> extends BinaryExpression<Boolean, V> {
	private static final long serialVersionUID = 2973872972306303687L;
	
	private final CompareOperator operator;

	public CompareExpression(Expression<V> lhs, Expression<V> rhs, CompareOperator operator) {
		super(lhs, rhs);
		this.operator = operator;
	}

	@Override
	protected final boolean canOperateWhenTypeMismatch(Context context, V lValue, V rValue) {
		if (Long.class.isInstance(lValue) && Double.class.isInstance(rValue)) {
			return true;
		} else if (Long.class.isInstance(rValue) && Double.class.isInstance(lValue)) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	protected Boolean operate(Context context, V lValue, V rValue, boolean typeMismatch) {
		if (typeMismatch) {
			if (Long.class.isInstance(lValue) && Double.class.isInstance(rValue)) {
				return compareTo(new Double(lValue.toString()), new Double(rValue.toString()));
			} else if (Long.class.isInstance(rValue) && Double.class.isInstance(lValue)) {
				return compareTo(new Double(lValue.toString()), new Double(rValue.toString()));
			} else {
				throw new IllegalArgumentException("二元操作两边的值类型不一致：左边[" + lValue.getClass() + "]；右边["
						+ rValue.getClass() + "]");
			}
		} else {
			return compareTo(lValue, rValue);
		}
	}

	private <E extends Comparable<E>> boolean compareTo(E lValue, E rValue) {
		switch (operator) {
		case EQ:
			return lValue.compareTo(rValue) == 0;
		case NE:
			return lValue.compareTo(rValue) != 0;
		case GT:
			return lValue.compareTo(rValue) > 0;
		case GE:
			return lValue.compareTo(rValue) >= 0;
		case LT:
			return lValue.compareTo(rValue) < 0;
		case LE:
			return lValue.compareTo(rValue) <= 0;
		default:
			throw new IllegalArgumentException("不支持的操作符：" + operator);
		}
	}
}
